5. w5500模块

您所在的位置:网站首页 flash 模块原理图 5. w5500模块

5. w5500模块

2023-08-17 13:28| 来源: 网络整理| 查看: 265

5.3.2. 例程介绍¶

本例程采用的硬件SPI,硬件SPI在《SPI基础知识》一文已经介绍,不再赘述,这里主要分析代码框架。

在编写w5500模块驱动时,也要考虑更改硬件环境的情况。我们把w5500模块引脚相关的宏定义到”w5500_config.h”文件中, 在更改或移植的时候只用改宏定义就可以。

程序中以SPI2作为w5500的硬件接口在w5500_config.h中定义,该头文件中还定义了一些相关数据结构,完整内容请参考w5500的 ping 例程。

w5500_config.h¶ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // ... ... #define WIZ_SPIx_GPIO_PORT GPIOB /* GPIO端口 */ #define WIZ_SPIx_GPIO_CLK RCC_APB2Periph_GPIOB /* GPIO端口时钟 */ #define WIZ_SPIx SPI2 /* 定义W5500所用的SPI接口 */ #define WIZ_SPIx_CLK_CMD RCC_APB1PeriphClockCmd #define WIZ_SPIx_CLK RCC_APB1Periph_SPI2 /* 定义W5500所用的SPI接口时钟 */ #define WIZ_SPIx_SCLK GPIO_Pin_13 /* 定义W5500的时钟管脚 */ #define WIZ_SPIx_MISO GPIO_Pin_14 /* 定义W5500的MISO管脚 */ #define WIZ_SPIx_MOSI GPIO_Pin_15 /* 定义W5500的MOSI管脚 */ // ... ... #define WIZ_SPIx_SCS GPIO_Pin_12 /* 定义W5500的片选管脚 */ #define WIZ_SPIx_SCS_PORT GPIOB /* GPIO端口 */ #define WIZ_SPIx_SCS_CLK RCC_APB2Periph_GPIOB /* GPIO端口时钟 */ #define WIZ_RESET GPIO_Pin_7 /* 定义W5500的RESET管脚 */ #define WIZ_SPIx_RESET_PORT GPIOC /* GPIO端口 */ #define WIZ_SPIx_RESET_CLK RCC_APB2Periph_GPIOC /* GPIO端口时钟 */ #define WIZ_INT GPIO_Pin_6 /* 定义W5500的INT管脚 */ #define WIZ_SPIx_INT_PORT GPIOC /* GPIO端口 */ #define WIZ_SPIx_INT_CLK RCC_APB2Periph_GPIOC /* GPIO端口时钟 */ // ... ...

接下来是w5500的接口初始化,用到的是SPI2,首先需要开启相应管脚的时钟,这里开启了控制w5500的RESET、INT、MISO、MOSI、CLK、及片选引脚的端口时钟,开启SPI2时钟, 设置SPI2的SCLK引脚的速率为50MHz,模式设置为复用输出模式,MISO和MOSI都采用与SCLK相同的配置,设置SPI2的SCS引脚为推挽输出。

SPI_DirectionSPI设置单向或者双向的数据模式,这里选择SPI设置为双线双向全双工;SPI_Mode是设置SPI工作模式,设置为主SPI;SPI_DataSize是设置数据传输的大小,设置为SPI发送接收8位帧; 设置串行同步时钟的空闲状态为高电平,串行同步时钟的第二个跳变沿(上升或下降)数据被采样;SPI_NSS是NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理,设置为内部NSS信号由SSI控制, SPI_BaudRatePrescaler为定义预分频,波特率预分频值为4;SPI_FirstBit是指定数据传输从MSB位还是LSB位开始,设置为数据传输从MSB位开始,SPI_CRCPolynomial为CRC值计算的多项式;

w5500_config.h¶ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 void gpio_for_w5500_config(void) { SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; /* 开启RESET、INT引脚端口时钟 */ RCC_APB2PeriphClockCmd(WIZ_SPIx_RESET_CLK|WIZ_SPIx_INT_CLK, ENABLE); /* 开启SPI2端口时钟和片选引脚时钟 */ RCC_APB2PeriphClockCmd(WIZ_SPIx_GPIO_CLK|WIZ_SPIx_SCS_CLK, ENABLE); /* SPI2时钟使能 */ WIZ_SPIx_CLK_CMD(WIZ_SPIx_CLK, ENABLE); /* 配置SPI2时钟管脚 */ GPIO_InitStructure.GPIO_Pin = WIZ_SPIx_SCLK; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用输出 GPIO_Init(WIZ_SPIx_GPIO_PORT, &GPIO_InitStructure); /* 配置SPI2 MISO */ GPIO_InitStructure.GPIO_Pin = WIZ_SPIx_MISO; GPIO_Init(WIZ_SPIx_GPIO_PORT, &GPIO_InitStructure); /* 配置SPI2 MOSI */ GPIO_InitStructure.GPIO_Pin = WIZ_SPIx_MOSI; GPIO_Init(WIZ_SPIx_GPIO_PORT, &GPIO_InitStructure); /* 配置SPI2片选引脚 */ GPIO_InitStructure.GPIO_Pin = WIZ_SPIx_SCS; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(WIZ_SPIx_SCS_PORT, &GPIO_InitStructure); /* SPI2 configuration */ SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧 SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平 SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号由SSI控制 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; //定义波特率预分频的值:波特率预分频值为256 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始 SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式 SPI_Init(WIZ_SPIx, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPI寄存器 SPI_Cmd(WIZ_SPIx, ENABLE); /* 定义RESET引脚 */ GPIO_InitStructure.GPIO_Pin = WIZ_RESET; /*选择要控制的GPIO引脚*/ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /*设置引脚速率为50MHz */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /*设置引脚模式为通用推挽输出*/ GPIO_Init(WIZ_SPIx_RESET_PORT, &GPIO_InitStructure); /*调用库函数,初始化GPIO*/ GPIO_SetBits(WIZ_SPIx_RESET_PORT, WIZ_RESET); /* 定义INT引脚 */ GPIO_InitStructure.GPIO_Pin = WIZ_INT; /*选择要控制的GPIO引脚*/ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /*设置引脚速率为50MHz*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; /*设置引脚模式为通用推挽模拟上拉输入*/ GPIO_Init(WIZ_SPIx_INT_PORT, &GPIO_InitStructure); /*调用库函数,初始化GPIO*/ }

然后我们来看一下main函数,初始化Systick工作时钟,初始化串口,波特率设置为115200,初始化eeprom用来保存5500配置,初始化MCU相关引脚, 硬复位W5500,配置MAC地址,配置IP地址,初始化8个Socket的发送接收缓存大小,可以访问8个IP地址,再循环执行ping函数。

main.c¶ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 int main(void) { /* 初始化Systick工作时钟 */ systick_init(72); /* 初始化串口通信:115200@8-n-1 */ USART1_Config(); /* 初始化eeprom */ i2c_CfgGpio(); printf(" 野火网络适配版 网络初始化 Demo V1.0 \r\n"); /* 初始化MCU相关引脚 */ gpio_for_w5500_config(); /* 硬复位W5500 */ reset_w5500(); /* 配置MAC地址 */ set_w5500_mac(); /* 配置IP地址 */ set_w5500_ip(); /* 初始化8个Socket的发送接收缓存大小 */ socket_buf_init(txsize, rxsize); printf(" 应用程序执行中…… \r\n"); while(1)//循环执行的函数 { /* 执行ping函数 */ do_ping(); if(req>=4) break; } while(1) {} }

最后看一下do_ping函数里做了些什么,在do_ping每秒执行一次自动PING外网IP函数ping_auto,每次进入到ping_auto中都会循环ping3次, 通过getSn_SR函数读写寄存器访问socket状态,socket会处于关闭状态或ip raw模式。

ping.c¶ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 void do_ping(void) { printf("------------PING_TEST_START-----------------------\r\n"); /* wait 1000ms */ delay_ms(1000); /* 自动PING外网IP函数 */ ping_auto(SOCK_PING,remote_ip); } void ping_auto(uint8 s, uint8 *addr) { uint8 i; int32_t len = 0; uint8 cnt=0; for(i = 0; i 0) { ping_reply(s, addr, len); /*获取回复信息*/ delay_us(500); // wait 50ms rep++; break; } else if(cnt > 200) { printf( "Request Time out. \r\n"); cnt = 0; break; } else { cnt++; delay_ms(1); // wait 50ms } // wait_time for 2 seconds, Break on fail } break; default: break; } #ifdef PING_DEBUG if(rep!=0) { printf("Ping Request = %d, PING_Reply = %d\r\n",req,rep); if(rep == req) printf( "PING SUCCESS\r\n " ); else printf( "REPLY_ERROR\r\n " ); } #endif } }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3